home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 4 / Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso / Pearls / dev / C-Lib / AsyncIO / source / Lib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-05  |  6.2 KB  |  233 lines

  1. /* Lib.c
  2.  *
  3.  * Basic Library Resource Handling
  4.  *
  5.  * This code is based on the example shared library,
  6.  * found on the DICE 3.0 disks.
  7.  *
  8.  * This code doesn't use any form of startup code (the example does).
  9.  * This is not something the novice C-programmer should attemt to do.
  10.  * You need to know what you are doing. :)
  11.  */
  12.  
  13. #include "async.h"
  14. #include <exec/libraries.h>
  15. #include <exec/resident.h>
  16. #include "rev.h"
  17.  
  18. #include <clib/asyncio_protos.h>
  19.  
  20. _ASM LibCall struct Library *LibInit( _REG( d0 ) struct Library *, _REG( a0 ) APTR, _REG( a6 ) struct ExecBase * );
  21. _ASM struct Library *LibOpen( _REG( a6 ) struct Library * );
  22. _ASM APTR LibClose( _REG( a6 ) struct Library * );
  23. _ASM APTR LibExpunge( _REG( a6 ) struct Library * );
  24.  
  25.  
  26. /* These variables will be zero, since "The memory used for bss
  27.  * blocks is zeroed by the loader when it is allocated" (quote
  28.  * from the AmigaDOS manual).
  29.  */
  30. struct Library        *AsyncIOBase;    /* Our library structure */
  31. struct ExecBase        *SysBase;
  32. struct Library        *UtilityBase;
  33. struct DosLibrary    *DOSBase;
  34. APTR            SegList;
  35.  
  36.  
  37. /* In case the user tries to run us, simply exit immediately.
  38.  * This code is also used for the reserved library function,
  39.  * that all libraries currently must have.
  40.  *
  41.  * Note that this function *must* be placed before any const
  42.  * data, or else the "exit if run" effect is lost (you are
  43.  * more likely to get a "crash if run" effect ;).
  44.  */
  45. LONG
  46. LibReserved( VOID )
  47. {
  48.     return( 0 );
  49. }
  50.  
  51.  
  52. /* The functions the library should have. Unfortunately, we can't
  53.  * use the more compact format, using 16-bit relative entries,
  54.  * due to the compiler (bug or limitation ;).
  55.  */
  56.  
  57. static const APTR FuncTable[] =
  58. {
  59.     LibOpen,    /* Standard library functions */
  60.     LibClose,
  61.     LibExpunge,
  62.     LibReserved,
  63.  
  64.     OpenAsync,    /* Our functions start here */
  65.     OpenAsyncFromFH,
  66.     CloseAsync,
  67.     SeekAsync,
  68.     ReadAsync,
  69.     WriteAsync,
  70.     ReadCharAsync,
  71.     WriteCharAsync,
  72.  
  73.     ( APTR ) -1    /* Terminate the table */
  74. };
  75.  
  76.  
  77. /* Table describing the library. We need this, since we use the
  78.  * autoinit feature. This means we don't need to call MakeLibrary()
  79.  * etc. in LibInit.
  80.  */
  81. static const ULONG InitTable[] =
  82. {
  83.     sizeof( struct Library ),    /* Size of our library base, excluding jump table. We have no extra data here */
  84.     ( ULONG ) FuncTable,        /* The functions we have */
  85.     NULL,                /* InitStruct data. We init stuff ourselves instead */
  86.     ( ULONG ) LibInit        /* The library init function */
  87. };
  88.  
  89.  
  90. static const TEXT LibId[] = "asyncio.library "VERSION" (" DATE ")\r\n";
  91. static const TEXT LibName[] = "asyncio.library";
  92.  
  93.  
  94. /* And finaly the resident structure, used by InitResident(),
  95.  * in order to initialize everything.
  96.  */
  97. static const struct Resident RomTag =
  98. {
  99.     RTC_MATCHWORD,        /* rt_MatchWord */
  100.     &RomTag,        /* rt_MatchTag */
  101.     LibExpunge,        /* rt_EndSkip */
  102.     RTF_AUTOINIT,        /* rt_Flags */
  103.     VERNUM,            /* rt_Version */
  104.     NT_LIBRARY,        /* rt_Type */
  105.     0,            /* rt_Pri */
  106.     LibName,        /* rt_Name */
  107.     LibId,            /* rt_IDString */
  108.     InitTable        /* rt_Init */
  109. };
  110.  
  111.  
  112. /* This small function frees the library structure,
  113.  * and any other allocated resources.
  114.  */
  115. static VOID
  116. FreeLib( struct Library *lib )
  117. {
  118.     if( DOSBase )    /* In case we are loaded under kick 35 or earlier */
  119.     {
  120.         CloseLibrary( ( struct Library * ) DOSBase );
  121.         CloseLibrary( UtilityBase );
  122.     }
  123.  
  124.     FreeMem( ( UBYTE * ) lib - lib->lib_NegSize, lib->lib_NegSize + lib->lib_PosSize );
  125. }
  126.  
  127.  
  128. /* This function is called when the library is loaded, and the library base
  129.  * have been allocated. We are in a forbid section here, so don't do anything
  130.  * time-consuming, Wait() or similar.
  131.  *
  132.  * If all ok, return the library base. If anything went wrong, deallocate
  133.  * the library structure, and return NULL.
  134.  */
  135. LibCall _ASM struct Library *
  136. LibInit( _REG( d0 ) struct Library *lib, _REG( a0 ) APTR seglist, _REG( a6 ) struct ExecBase *sysBase )
  137. {
  138.     SysBase = sysBase;
  139.  
  140.     if( ( DOSBase = ( struct DosLibrary * ) OpenLibrary( "dos.library", 37 ) ) &&
  141.         ( UtilityBase = OpenLibrary( "utility.library", 37 ) ) )
  142.     {
  143.         lib->lib_Node.ln_Type    = NT_LIBRARY;
  144.         lib->lib_Node.ln_Pri    = 0;
  145.         lib->lib_Node.ln_Name    = LibName;
  146.         /* Request that checksum should be calculated */
  147.         lib->lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
  148.         lib->lib_Version    = VERNUM;
  149.         lib->lib_Revision    = REVNUM;
  150.         lib->lib_IdString    = ( APTR ) LibId;
  151.         SegList = seglist;
  152.         AsyncIOBase = lib;
  153.     }
  154.     else
  155.     {
  156.         FreeLib( lib );
  157.         lib = NULL;
  158.     }
  159.  
  160.     return( lib );
  161. }
  162.  
  163.  
  164. /* Open is given the library pointer. Either return the library pointer or NULL.
  165.  * Remove the delayed-expunge flag. Exec has Forbid() for us during the call.
  166.  *
  167.  * Since we don't refer to any smalldata here (directly or indirectly),
  168.  * we can safely skip "LibCall", to save a few bytes.
  169.  */
  170. _ASM struct Library *
  171. LibOpen( _REG( a6 ) struct Library *lib )
  172. {
  173.     ++lib->lib_OpenCnt;
  174.     lib->lib_Flags &= ~LIBF_DELEXP;
  175.     return( lib );
  176. }
  177.  
  178.  
  179. /* Close is given the library pointer. Be sure not to decrement the open
  180.  * count if already zero. If the open count is or becomes zero AND there
  181.  * is a LIBF_DELEXP, we expunge the library and return the seglist.
  182.  * Otherwise we return NULL.
  183.  *
  184.  * Note that this routine never sets LIBF_DELEXP on its own.
  185.  *
  186.  * Exec has Forbid() for us during the call.
  187.  *
  188.  * Since we don't refer to any smalldata here (directly. Indirectly we refer via
  189.  * LibExpunge, which is LibCall declared), we can safely skip "LibCall", to save
  190.  * a few bytes.
  191.  */
  192. _ASM APTR
  193. LibClose( _REG( a6 ) struct Library *lib )
  194. {
  195.     if( lib->lib_OpenCnt && --lib->lib_OpenCnt )
  196.     {
  197.         return( NULL );
  198.     }
  199.  
  200.     if( lib->lib_Flags & LIBF_DELEXP )
  201.     {
  202.         return( LibExpunge( lib ) );
  203.     }
  204.  
  205.     return( NULL );
  206. }
  207.  
  208.  
  209. /* We expunge the library and return the Seglist ONLY if the open count is zero.
  210.  * If the open count is not zero we set the delayed-expunge flag and return NULL.
  211.  *
  212.  * Exec has Forbid() for us during the call. NOTE ALSO that Expunge might be
  213.  * called from the memory allocator and thus we CANNOT DO A Wait() or otherwise
  214.  * take a long time to complete (straight from RKM).
  215.  *
  216.  * RemLibrary() calls our expunge routine and would therefore freeze if we called
  217.  * it ourselves. LibExpunge() must remove the library itself as shown below.
  218.  */
  219. LibCall _ASM APTR
  220. LibExpunge( _REG( a6 ) struct Library *lib )
  221. {
  222.     if( lib->lib_OpenCnt )
  223.     {
  224.         lib->lib_Flags |= LIBF_DELEXP;
  225.         return( NULL );
  226.     }
  227.  
  228.     Remove( &lib->lib_Node );
  229.     FreeLib( lib );
  230.  
  231.     return( SegList );
  232. }
  233.